#ifndef BLOQUEHOJA_H_
#define BLOQUEHOJA_H_

#include "BloqueInterno.h"
#include "BloqueArbol.h"
#include "Arbol.h"
#include "../Elemento.h"
#include "../../claves/TipoClave.h"
class TipoClave;

class BloqueHoja : public BloqueArbol {

private:
	offset siguiente;
	TipoClave* extractor;

public:
	/*
	 * Pre: -
	 * Pos: Crea una nueva instancia.
	 */
	BloqueHoja(Arbol* a,cantBytes tamanio,TipoClave* extractor);

	/*
	 * Pre: -
	 * Pos: Libera los recursos instanciados.
	 */
	virtual ~BloqueHoja();

	  /*Le seteo al nodo su hermano siguiente*/
	    void setHermano(offset hermano);
	/*
	 * Pre: -
	 * Pos: devuelve el tipo del bloque hoja 'h'.
	 */
	virtual char getTipo();

	/*
	 * Pre: -
	 * Pos: devuelve el offset del hermano siguiente.
	 */
	virtual offset getSiguiente();



	/*
	 * Pre: -
	 * Pos: serializa el estado del objeto.
	 */
	virtual Bytes serializarse();

	/*
	 * Pre: -
	 * Pos: hidrata el estado del objeto.
	 */
    virtual bool hidratarse(const Bytes& bytes);


    /*Retorna el hijo con las menores claves que  contiene el Nodo*/
    BloqueArbol* getHijoMenor();

    /*Retorno el nodo donde estaba ese elemento que se inserto,
     * el resultado de la operacion se retorna res, Si no se pue realizar la operacion
     * en el retorno se devuelve NULL */
    virtual BloqueArbol* insertarElemento(const Elemento& elemento, Resultado& res, bool& overflow);

    /*Le paso una clave que estoy buscando, el me devolvera el puntero correspondiente al Elemento
     * si no lo encuentra devuelve null */
    virtual offset getElemento(const Key& clave, Resultado& res);

    /*pre: ver que nodo hermano no quede en overflow.
     * this se setea a borrado y todas las claves e hijos pasan a nodohermano*/
    bool dosAUno(BloqueHoja* nodoHermano);

    /*Se retorna el padre del nodo que quedÃ³ en underflow.
     * En este metodo se resuelve el underflow invocando diferentes metodos
     * segun la estructura del arbol en ese momento. En clave vieja se
     * incluye la clave que se borro generando el underflow, en res, retorno
     * si se logrÃ³ realizar la operacion*/
    BloqueInterno* underflowHoja(Resultado& res,const Key& claveVieja);

    /*igual al merge pero para overflows*/
    bool balancearDosHojas(BloqueHoja* nodo, BloqueHoja* hermano);

    /*El nodo que invoca es el padre de los tres.
    	*PRE: debe recibirlos en el orden que se balancearan
    	*indico en el campo 3a2 : true para undreflow:Se redistribuyen las claves en solo dos nodos, y se borra el nodo del medio
    	 *  y false para overflow: se llama con hermanoIzq y hermano y nodo vacÃ­o (el nuevo nodo)*/
    Resultado mergeTresHojas(BloqueHoja* hermanoIzq, BloqueHoja* nodo, BloqueHoja* hermano, bool tresADos);

    /*Retorno el nodo donde estaba ese elemento que se inserto,
    	 * el resultado de la operacion se retorna en res
    *Si no se pue realizar la operacion en el retorno se devuelve NULL
    	 *Se crea un hermano y un padre, que se retorna y es la nueva raiz del arbol*/
    BloqueInterno* overflowRaizHoja(Resultado& res);

    /*Se retorna el padre del nodo que quedo en overflow.
    * En este metodo se resuelve el overflow invocando diferentes metodos
    * segun la estructura del arbol en ese momento. En res, retorno
    * si se logrÃ³ realizar la operacion*/
    BloqueInterno* overflowHoja(Resultado& res);

    /* Se retorna el hermano siguiente*/
    BloqueHoja* getHermano();

    /*se invoca overflowHoja o overflowRaizHoja segun tenga o no padre*/
    BloqueInterno* resolverOverflow();

 /*se invoca underflowHoja (se deja por coherencia de interfaces)*/
    void resolverUnderflow(const Key& claveVieja);

    void resolverOverRaiz();

    /*Retorno el nodo Retorno el nodo donde estaba ese elemento que se borro,
     * el resultado de la operacion se retorna res, Si no se pue realizar la operacion
     * en el retorno se devuelve NULL */
    virtual BloqueArbol* removerElemento(const Elemento& elemento, Resultado& res);

    /*Al ser un nodo hoja se retorna a siÂ­ mismo puesto que sirve para el metodo recursivo de
     * insertar del arbol*/
    virtual BloqueArbol* buscarHijo(const Key& claveABuscar);

        /*se retorna la mayor clave de la rama que surge desde ahi*/
    virtual Key getMayorDeRama();

    /*retorna las claves en un string*/
    virtual std::string clavesToString();

    virtual unsigned getCantClaves()const;

    /*se imprimen las claves del vector por consola*/
    virtual void imprimir();



    void actualizarSiguiente();


};

#endif /* BLOQUEHOJA_H_ */
